package com.jacky.iot.service;

import com.google.common.collect.Lists;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.jacky.iot.commons.Cmd;
import com.jacky.iot.commons.InstantTypeAdapter;
import com.jacky.iot.dtos.TimeCmd;
import com.jacky.iot.dtos.WebSocketReq;
import com.jacky.iot.tasks.WebSocketScheduleTask;
import com.jacky.iot.utils.ShortUUID;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.time.Instant;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

@Component
public class WebSocketFetchDataService {
    private final static Logger LOG = LoggerFactory.getLogger(WebSocketFetchDataService.class);

    private final Map<WebSocketSession, List<String>> fetchIdMap = new ConcurrentHashMap<>();
    private final Map<String/*fetchId*/, String/*taskId*/> fetchTaskMap = new ConcurrentHashMap<>();

    private final Gson gson;
    private final ScheduledTaskManager taskManager;
    private final CpuUsageService usageService;

    public WebSocketFetchDataService(Gson gson, ScheduledTaskManager taskManager, CpuUsageService usageService) {
        this.gson = gson;
        this.taskManager = taskManager;
        this.usageService = usageService;
    }

    /**
     * 处理数据的拉取，更新，取消
     *
     * @param session
     * @param wsr
     */
    public void handleDataFetch(WebSocketSession session, WebSocketReq wsr) {
        try {
            if (StringUtils.isBlank(wsr.getFetchId())) {
                TextMessage txm = new TextMessage("fetchId can not be null");
                session.sendMessage(txm);
            } else {
                TimeCmd windowTC = wsr.getWindowTC();
                if (Objects.isNull(windowTC)) {
                    windowTC = new TimeCmd(10, TimeUnit.MINUTES);
                }
                TimeCmd intervalTC = wsr.getIntervalTC();
                if (Objects.isNull(intervalTC)) {
                    intervalTC = new TimeCmd(10, TimeUnit.SECONDS);
                }
                TaskWrapper taskWrapper = new TaskWrapper();
                taskWrapper.setTaskId(ShortUUID.shortUUId());
                taskWrapper.setTask(new WebSocketScheduleTask(session, usageService, wsr.getDfw(), windowTC));
                taskWrapper.setInterval(intervalTC.getTime());
                taskWrapper.setIntervalTU(intervalTC.getTimeUnit());

                String elderTaskId = fetchTaskMap.get(wsr.getFetchId());
                if (wsr.getCmd().equals(Cmd.FETCH_DATA)) {
                    if (StringUtils.isBlank(elderTaskId)) {
                        taskManager.newScheduledTask(taskWrapper);
                        fetchTaskMap.put(wsr.getFetchId(), taskWrapper.getTaskId());
                        if (!fetchIdMap.containsKey(session)) {
                            fetchIdMap.put(session, Lists.newArrayList(wsr.getFetchId()));
                        } else {
                            fetchIdMap.get(session).add(wsr.getFetchId());
                        }
                    } else {
                        taskManager.updateTask(elderTaskId, taskWrapper);
                        fetchTaskMap.put(wsr.getFetchId(), taskWrapper.getTaskId());
                        TextMessage tm = new TextMessage("【%s】拉取请求已更新".formatted(wsr.getFetchId()));
                        session.sendMessage(tm);
                    }
                } else if (wsr.getCmd().equals(Cmd.UPDATE_FETCH_INTERVAL)) {
                    taskManager.updateTask(elderTaskId, taskWrapper);
                    fetchTaskMap.put(wsr.getFetchId(), taskWrapper.getTaskId());
                    TextMessage tm = new TextMessage("【%s】拉取请求已更新".formatted(wsr.getFetchId()));
                    session.sendMessage(tm);
                } else if (wsr.getCmd().equals(Cmd.CANCEL_FETCH_DATA)) {
                    taskManager.cancelTask(elderTaskId);
                    TextMessage tm = new TextMessage("【%s】拉取请求已取消".formatted(wsr.getFetchId()));
                    session.sendMessage(tm);
                }

            }
        } catch (Exception e) {
            LOG.error("handle data fetch error:", e);
        }
    }

    public void handleSessionClose(WebSocketSession session) {
        List<String> fetchIds = fetchIdMap.get(session);
        fetchIds.forEach(fetchId -> {
            String taskId = fetchTaskMap.get(fetchId);
            taskManager.cancelTask(taskId);
        });
    }
}
